using ValidationFramework.Extensions;
using ValidationFramework.Configuration.Xml;
using ValidationFramework.Configuration;

namespace ValidationFramework.Specifications
{
    /// <summary>
    /// A <see cref="IRuleConfigReader"/> that creates a <see cref="CustomRule"/> from a <see cref="RuleData"/>.
    /// </summary>
    /// <remarks>
    ///   <see cref="RuleData"/> for default attributes.
    ///   <b>Extra Attributes</b>
    ///   <ul>
    ///     <li>
    ///       <c>ruleInterpretation</c> (required): Used to populate <see cref="CustomRule.RuleInterpretation"/>.  
    ///     </li>
    ///     <li>
    ///       <c>validationMethod</c> (required): Used to populate <see cref="CustomRule.Handler"/>.   
    ///     </li>
    ///     <li>
    ///       <c>validationTypeName</c> (required): Used to populate <see cref="CustomRule.Handler"/>.   
    ///     </li>
    ///   </ul>
    /// </remarks>
    /// <example>
    /// <code lang="xml" title="This example shows an xml configuration for CustomRuleConfigReader">
    /// <rule 
    /// ruleInterpretation="This is a custom rule" 
    /// validationMethod="ValMethod" 
    /// validationTypeName="MyNamespace.MyType,MyAssembly" 
    /// errorMessage="hello" 
    /// typeName="CustomRule"/>
    /// </code>
    /// </example>
    /// <example>
    /// The following example shows how to add a <see cref="CustomRule"/> using xml configuration. 
    /// <code source="Examples\ExampleLibraryCSharp\Configuration\CustomRuleConfigReaderExample.cs" lang="cs"/>
    /// </example>
    /// <seealso cref="CustomRule"/>
    /// <seealso cref="ConfigurationService"/>
    public sealed class SatisfiesDelegateParser : ISpecificationXmlParser
    {
		public ISpecification GetSpecification(System.Xml.XmlElement SpecificationElement, RuleContext context)
		{
			Guard.ArgumentNotNull(SpecificationElement, "SpecificationElement");

			var validationTypeName = SpecificationElement.GetAttribute<string>("validationTypeName");
			var validationMethod = SpecificationElement.GetAttribute<string>("validationMethod");
			var ruleInterpretation = SpecificationElement.GetAttribute<string>("ruleInterpretation");

			var method = SatisfiesDelegateSpec.ResolveValidateMethod(validationTypeName, validationMethod);

			return new SatisfiesDelegateSpec(method, ruleInterpretation);
		}
	}
}